/*
 * Copyright (C) 2004 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.desktop.workbench;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;

import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.desktop.WorkbenchFrame;
import nu.zoom.swing.desktop.WorkbenchMenuBar;
import nu.zoom.swing.desktop.component.ASF2LicensePanel;

import org.ops4j.gaderian.Messages;

/**
 * Implementation os the workbench menu bar.
 * 
 * @version $Revision: 1.8 $
 * @author $Author: johan $
 */
public class WorkbenchMenuBarImpl implements WorkbenchMenuBar {

	private Hashtable<String, JMenu> menues = new Hashtable<String, JMenu>();

	private JMenuBar menuBar;

	private Workbench workbench;

	private JMenu helpMenu = null;

	private JMenu applicationMenu = null;

	private Messages messages;

	public WorkbenchMenuBarImpl(Workbench workbench, Messages messages) {
		this.workbench = workbench;
		this.messages = messages;
		menuBar = new JMenuBar();

		String applicationMenuTitle = messages.getMessage("menu.application");
		applicationMenu = new JMenu(applicationMenuTitle);
		applicationMenu.setMnemonic(KeyEvent.VK_A);
		applicationMenu.addSeparator();
		ExitAction exitAction = new ExitAction(messages.getMessage("menuitem.exit"));
		JMenuItem exitMenuItem = new JMenuItem(exitAction);
		exitMenuItem.setMnemonic(KeyEvent.VK_X);
		applicationMenu.add(exitMenuItem);

		String helpMenuTitle = messages.getMessage("menu.help");
		helpMenu = new JMenu(helpMenuTitle);
		helpMenu.setMnemonic(KeyEvent.VK_P);
		helpMenu.add(new LicenseAction(messages.getMessage("menuitem.license")));

		buildMenuBar();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see nu.zoom.swing.desktop.gui.WorkbenchMenuBar#addMenu(java.lang.String,
	 * javax.swing.JMenu)
	 */
	public void addMenu(final String menuKey, final JMenu menu) throws IllegalArgumentException {
		if ((menuKey == null) || (menuKey.length() < 1)) {
			throw new IllegalArgumentException("Menu key can not be null or zero length");
		}
		if (menu == null) {
			throw new IllegalArgumentException("Can not add null for menu value");
		}
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				addMenuImpl(menuKey, menu);
			}
		});
	}

	private void buildMenuBar() {
		menuBar.add(applicationMenu);
		Enumeration<String> keyEnum = menues.keys();
		while (keyEnum.hasMoreElements()) {
			JMenu currentMenu = menues.get(keyEnum.nextElement());
			menuBar.add(currentMenu);
		}
		menuBar.add(helpMenu);
		menuBar.revalidate();
	}

	private synchronized void addMenuImpl(String menuKey, JMenu menu) {
		menuBar.removeAll();
		menues.put(menuKey, menu);
		buildMenuBar();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see nu.zoom.swing.desktop.gui.WorkbenchMenuBar#getMenu(java.lang.String)
	 */
	public JMenu getMenu(final String menuKey) {
		if (APPLICATION_MENU_KEY.equals(menuKey)) {
			return applicationMenu;
		} else if (HELP_MENU_KEY.equals(menuKey)) {
			return helpMenu;
		} else {
			return menues.get(menuKey);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * nu.zoom.swing.desktop.gui.WorkbenchMenuBar#removeMenu(java.lang.String)
	 */
	public void removeMenu(final String menuKey) {
		if ((menuKey != null) && (menuKey.length() > 0) && (!menuKey.equals(HELP_MENU_KEY))
				&& (!menuKey.equals(APPLICATION_MENU_KEY))) {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					removeMenuImpl(menuKey);
				}
			});
		}
	}

	private synchronized void removeMenuImpl(String menuKey) {
		JMenu removedMenu = menues.remove(menuKey);
		if (removedMenu != null) {
			menuBar.removeAll();
			buildMenuBar();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see nu.zoom.swing.desktop.gui.WorkbenchMenuBar#getJMenuBar()
	 */
	public JMenuBar getJMenuBar() {
		return menuBar;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * nu.zoom.swing.desktop.gui.WorkbenchMenuBar#addToApplicationMenu(javax
	 * .swing.JMenuItem)
	 */
	public void addToApplicationMenu(final JMenuItem item) throws IllegalArgumentException {
		if (item == null) {
			throw new IllegalArgumentException("item to add to application menu can not be null");
		}
		if (EventQueue.isDispatchThread()) {
			applicationMenu.insert(item, 0);
		} else {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					applicationMenu.insert(item, 0);
				}
			});
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * nu.zoom.swing.desktop.gui.WorkbenchMenuBar#addToHelpMenu(javax.swing.
	 * JMenuItem)
	 */
	public void addToHelpMenu(final JMenuItem item) throws IllegalArgumentException {
		if (item == null) {
			throw new IllegalArgumentException("item to add to application menu can not be null");
		}
		if (EventQueue.isDispatchThread()) {
			helpMenu.add(item);
		} else {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					helpMenu.add(item);
				}
			});
		}
	}

	@SuppressWarnings("serial")
	class LicenseAction extends AbstractAction {

		LicenseAction(String title) {
			super(title);
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			WorkbenchFrame frame =
					workbench.createWorkbenchFrame(ASF2LicensePanel.class.getName(), new ASF2LicensePanel(), null,
							true, true);
			frame.setTitle(messages.getMessage("window.title.license"));
			frame.setVisible(true);
		}
	}

	@SuppressWarnings("serial")
	class ExitAction extends AbstractAction {

		ExitAction(String title) {
			super(title);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			workbench.close();
		}
	}
}